#include "../include/BaseSocket.h"
#include "../include/Utility.hpp"
#include <assert.h>
BaseSocket::BaseSocket()
{
	m_sockFd = INVALID_SOCKET;
#ifdef  _WIN64 || _WIN32
	StartupWinSocket();
#endif // _WIN32 || _WIN64
}

BaseSocket::~BaseSocket()
{
	CloseSocket();
}

bool BaseSocket::StartupWinSocket()
{
#ifdef  _WIN64 || _WIN32
	WORD _version = MAKEWORD(2, 2);
	WSADATA _ws;
	if (WSAStartup(_version, &_ws) < 0)
	{
		LogPrint(LogType::ERR, "init socket fail~");
		WSACleanup();
		return false;
	}
#endif // _WIN32 || _WIN64
	return true;
}

bool BaseSocket::CreateSocket(const INT _af, const int32_t _type, const int32_t _protocol)
{
	m_sockFd = socket(_af, _type, _protocol);
	if (m_sockFd == INVALID_SOCKET)
	{
		LogPrint(LogType::ERR,"Create socket fail~");
		return false;
	}
	return true;
}

void BaseSocket::SetNonBlackSocket(SOCKET _sockFd, u_long mode)
{
#ifdef  _WIN64 || _WIN32
	auto result = ioctlsocket(_sockFd, FIONBIO, &mode);
	if (SOCKET_ERROR == result)
	{
		return;
	}
#else
	int32_t flags = fcntl(_sockFd, F_GETFL, 0);
	if (flags < 0)
	{
		return;
	}
	flags = (flags) ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
	if (fcntl(_sockFd, F_SETFL, flags) != 0)
	{
		return;
	}
#endif
}

bool BaseSocket::GetNonBlackModel(SOCKET _sockFd)
{
#ifdef  _WIN64 || _WIN32
	u_long nonBlocking = 0;
	int32_t result = ioctlsocket(_sockFd, FIONBIO, &nonBlocking);
	if (SOCKET_ERROR == result)
	{
		return false;
	}
	return !nonBlocking;
#else

	int32_t flag = fcntl(_sockFd, F_GETFL, 0);
	if (flags == -1)
	{
		return false;
	}
	return (flags & O_NONBLOCK) == 0;
#endif
}

void BaseSocket::SetRecvBuffSize(uint32_t _size)
{
	setsockopt(m_sockFd, SOL_SOCKET, SO_SNDBUF, (const char*)&_size, sizeof(_size));
}

void BaseSocket::SetSendBuffSize(uint32_t _size)
{
	setsockopt(m_sockFd, SOL_SOCKET, SO_RCVBUF, (const char*)&_size, sizeof(_size));
}

int32_t BaseSocket::GetRecvBuffSize()
{
	int32_t buffSize = 0;
	int32_t optlen = sizeof(buffSize);
	if (getsockopt(m_sockFd, SOL_SOCKET, SO_RCVBUF, (char*)&buffSize, &optlen) < 0)
	{
		return buffSize;
	}
	return 0;
}

int32_t BaseSocket::GetSendBuffSize()
{
	int32_t buffSize = 0;
	int32_t optlen = sizeof(buffSize);
	if (getsockopt(m_sockFd, SOL_SOCKET, SO_SNDBUF, (char*)&buffSize, &optlen) < 0)
	{
		return buffSize;
	}
	return 0;
}

void BaseSocket::CloseSocket()
{
#ifdef  _WIN64 || _WIN32
	if (m_sockFd != INVALID_SOCKET)
		::closesocket(m_sockFd);
	WSACleanup();
#else
	close(m_sockFd);
#endif
}